Fork me on GitHub

Ansible Playbook

Playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合.

Playbooks 的格式是YAML 语法做到最小化,意在避免 playbooks 成为一种编程语言或是脚本

playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用。playbook命令根据自上而下的顺序依次执行。‘plays’ 好似音符,playbook 好似由 ‘plays’ 构成的曲谱,通过 playbook,可以编排步骤进行多机器的部署,比如在 webservers 组的所有机器上运行一定的步骤, 然后在 database server 组运行一些步骤,最后回到 webservers 组,再运行一些步骤,诸如此类.使得你可以实现一些复杂的部署机制,这是ansible命令无法实现的。

playbook通过ansible-playbook命令使用,它的参数和ansible命令类似,ansible-playbook的简单使用方法:

1
ansible-playbook example-play.yml

一、一个简单的示例

下面是一个简单的ansible-playbook示例,可以了解其构成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted

二、playbook的构成

playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用。将多个play组织在一个playbook中即可以让它们联同起来按事先编排的机制同唱一台大戏。其主要有以下四部分构成:

1
2
3
4
5
playbooks组成:
Target section: 定义将要执行 playbook 的远程主机组
Variable section: 定义 playbook 运行时需要使用的变量
Task section: 定义将要在远程主机上执行的任务列表
Handler section: 定义 task 执行完成以后需要调用的任务

而其对应的目录层为五个,如下:

1
2
3
4
5
6
一般所需的目录层有:(视情况可变化)
vars 变量层
tasks 任务层
handlers 触发条件
files 文件
template 模板

1、Hosts和Users

playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。

  • hosts:用于指定要执行指定任务的主机其可以是一个或多个由冒号分隔主机组。
  • remote_user :用于指定远程主机上的执行任务的用户。不过remote_user也可用于各task中。也可以通过指定其通过sudo的方式在远程主机上执行任务其可用于play全局或某任务。此外甚至可以在sudo时使用sudo_user指定sudo时切换的用户。
  • user:于remote_user相同
  • sudo:如果设置为yes,执行该任务组的用户在执行任务的时候,获取root权限
  • sudo_user:如果设置user为breeze,sudo为yes,sudo_user为bernie时,则breeze用户在执行任务时会获得bernie用户的权限
  • gather_facts:除非明确说明不需要在远程主机上执行setup模块,否则默认自动执行。如果确实不需要setup模块传递过来的变量,则可以将该选项设置为False

2、任务列表和action

play的主体部分是任务列表。任务列表中的各任务按次序逐个在hosts中指定的所有主机上执行即在所有主机上完成第一个任务后再开始第二个。在自上而下运行某playbook时如果中途发生错误,所有已执行任务都将回滚因此在更正playbook后重新执行一次即可。

​ task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。module 具有”幂等”性,所以当远端系统被人改动时,可以重放 playbooks 达到恢复的目的. playbooks 本身可以识别这种改动,并且有一个基本的 event system(事件系统),可以响应这种改动.

每个task都应该有其name用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name则action的结果将用于输出。

1
2
3
tasks:
- name: make sure apache is running
service: name=httpd state=running

如果命令或脚本的退出码不为零可以使用如下方式替代

1
2
3
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true

使用ignore_errors来忽略错误信息

1
2
3
4
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True

3、handlers: 在发生改变时执行的操作

“notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler也即notify中调用handler中定义的操作。

注意:在notify中定义内容一定要和tasks中定义的 - name 内容一样,这样才能达到触发的效果,否则会不生效。

1
2
3
4
5
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
1
2
3
4
5
6
#handler是task列表这些task与前述的task并没有本质上的不同。
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted

4、tags

tags用于让用户选择运行或略过playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时如果确信其没有变化就可以通过tags跳过这些代码片断。

三、列出影响的主机

在执行一个 playbook 之前,想看看这个 playbook 的执行会影响到哪些 hosts,你可以这样做:

1
ansible-playbook playbook.yml --list-hosts

执行一个 playbook

如何运行一个 playbook 呢?这很简单,这里的示例是并行的运行 playbook,并行的级别 是10

1
ansible-playbook playbook.yml -f 10
好记性不如烂笔头,生命不息,学习不止!

分享